using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Update.Utils.Interfaces;

namespace Update.Utils.IO
{
    /// <summary>
    /// 文件操作辅助类
    /// </summary>
    public class FileHelper : IFileHelper
    {
        /// <summary>
        /// 检查文件是否被占用
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>是否被占用</returns>
        public bool IsFileInUse(string filePath)
        {
            try
            {
                using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
                {
                    // 如果能够以独占方式打开文件，则文件未被占用
                    return false;
                }
            }
            catch (IOException)
            {
                // 如果抛出IOException，文件可能被占用
                return true;
            }
            catch
            {
                // 其他异常，为安全起见返回false
                return false;
            }
        }

        /// <summary>
        /// 尝试结束占用文件的进程
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="processName">进程名，如果为null则自动检测</param>
        /// <param name="logger">日志记录回调</param>
        /// <returns>是否成功结束进程</returns>
        public bool TerminateProcessesUsingFile(string filePath, string processName, Action<string> logger = null)
        {
            try
            {
                if (string.IsNullOrEmpty(processName))
                {
                    // 这里需要使用更复杂的方法检测占用进程
                    // 通常需要调用Windows API或使用Handle.exe等工具
                    logger?.Invoke("无法自动检测占用进程，请手动关闭相关应用程序");
                    return false;
                }

                Process[] processes = Process.GetProcessesByName(processName);
                
                if (processes.Length == 0)
                {
                    logger?.Invoke($"找不到占用文件的进程: {processName}");
                    return false;
                }
                
                foreach (Process process in processes)
                {
                    try
                    {
                        logger?.Invoke($"正在结束进程: {process.ProcessName} (ID: {process.Id})");
                        process.Kill();
                        process.WaitForExit(2000); // 等待进程结束，最多2秒
                    }
                    catch (Exception ex)
                    {
                        logger?.Invoke($"结束进程失败: {process.ProcessName}, 错误: {ex.Message}");
                        return false;
                    }
                }
                
                return true;
            }
            catch (Exception ex)
            {
                logger?.Invoke($"查找占用进程失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 创建目录（如果不存在）
        /// </summary>
        /// <param name="directoryPath">目录路径</param>
        public void CreateDirectoryIfNotExists(string directoryPath)
        {
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }
        }

        /// <summary>
        /// 安全删除文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>是否成功删除</returns>
        public bool SafeDeleteFile(string filePath)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 获取临时目录路径
        /// </summary>
        /// <param name="subDir">子目录名称</param>
        /// <returns>临时目录完整路径</returns>
        public string GetTempDirectory(string subDir = "AppUpdater")
        {
            string tempDir = Path.Combine(Path.GetTempPath(), subDir);
            CreateDirectoryIfNotExists(tempDir);
            return tempDir;
        }

        /// <summary>
        /// 提取更新包
        /// </summary>
        /// <param name="zipPath">更新包路径</param>
        /// <param name="targetDir">目标目录</param>
        /// <param name="forceOverwrite">是否强制覆盖</param>
        /// <param name="autoTerminateProcesses">是否自动结束占用进程</param>
        /// <param name="targetAppExe">目标应用程序文件名</param>
        /// <param name="logger">日志记录回调</param>
        /// <returns>操作结果和跳过的文件列表</returns>
        public (bool Success, List<string> SkippedFiles) ExtractUpdatePackage(
            string zipPath, 
            string targetDir, 
            bool forceOverwrite, 
            bool autoTerminateProcesses, 
            string targetAppExe,
            Action<string> logger = null)
        {
            List<string> skippedFiles = new List<string>();
            bool success = true;

            try
            {
                // 确保目标目录存在
                CreateDirectoryIfNotExists(targetDir);
                
                // 使用ProcessStartInfo调用系统的解压工具
                success = ExtractZipWithCmd(zipPath, targetDir, forceOverwrite, logger, out skippedFiles);
                
                return (success, skippedFiles);
            }
            catch (Exception ex)
            {
                logger?.Invoke($"解压更新包失败: {ex.Message}");
                return (false, skippedFiles);
            }
        }

        /// <summary>
        /// 使用CMD命令解压文件
        /// </summary>
        private bool ExtractZipWithCmd(
            string zipPath, 
            string targetDir, 
            bool forceOverwrite,
            Action<string> logger, 
            out List<string> skippedFiles)
        {
            skippedFiles = new List<string>();
            
            try
            {
                // 使用ProcessStartInfo调用系统的解压工具
                var processInfo = new ProcessStartInfo
                {
                    FileName = "cmd.exe",
                    Arguments = $"/c powershell -Command \"& {{Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory('{zipPath}', '{targetDir}', {(forceOverwrite ? "$true" : "$false")})}}\"",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                };

                using (var process = Process.Start(processInfo))
                {
                    // 读取标准输出
                    string output = process.StandardOutput.ReadToEnd();
                    string error = process.StandardError.ReadToEnd();
                    
                    process.WaitForExit();
                    
                    if (process.ExitCode != 0)
                    {
                        logger?.Invoke($"解压失败，错误信息: {error}");
                        
                        // 尝试备用方法
                        return TryFallbackExtraction(zipPath, targetDir, logger);
                    }
                    
                    if (!string.IsNullOrEmpty(output))
                    {
                        logger?.Invoke($"解压输出: {output}");
                    }
                    
                    return true;
                }
            }
            catch (Exception ex)
            {
                logger?.Invoke($"解压更新包异常: {ex.Message}");
                return TryFallbackExtraction(zipPath, targetDir, logger);
            }
        }

        /// <summary>
        /// 尝试备用解压方法
        /// </summary>
        private bool TryFallbackExtraction(string zipPath, string targetDir, Action<string> logger)
        {
            try
            {
                // 备用方法：使用cmd的expand命令
                var expandInfo = new ProcessStartInfo
                {
                    FileName = "cmd.exe",
                    Arguments = $"/c mkdir \"{targetDir}\" & cd /d \"{targetDir}\" & tar -xf \"{zipPath}\"",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                };

                using (var process = Process.Start(expandInfo))
                {
                    // 读取标准输出
                    string output = process.StandardOutput.ReadToEnd();
                    string error = process.StandardError.ReadToEnd();
                    
                    process.WaitForExit();
                    
                    if (process.ExitCode != 0)
                    {
                        logger?.Invoke($"备用解压失败，错误信息: {error}");
                        return false;
                    }
                    
                    return true;
                }
            }
            catch (Exception ex2)
            {
                logger?.Invoke($"备用解压方法异常: {ex2.Message}");
                return false;
            }
        }
    }
} 